#include "ClientSocket.h"
#include <QMessageBox>

#define MAXDATACACHESIZE 2048

TcpSocket::TcpSocket(QObject * parent)
    : QTcpSocket(parent),
      m_dsOut(&m_baOutBlock,QIODevice::WriteOnly),
      //mutexOutBlock(QMutex::Recursive),
      m_dsIn(this)
{
    connect(&m_timerHeart, &QTimer::timeout, this, [=](){
        if(isOpen())
            //write(m_pDataHeart, m_nDataHeartLength);
            write(m_baHeart);
    });


    connect(this, SIGNAL(hostFound()), this, SLOT(onHostFound()));

    //连接函数
    connect(this, SIGNAL(connected()), this, SLOT(onConnected()));
    //断开
    connect(this, SIGNAL(disconnected()), this, SLOT(onDisconnected()));

    connect(this, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
            this, SLOT(onStateChanged(QAbstractSocket::SocketState)));

    //错误函数
    //connect(this, SIGNAL(error(QAbstractSocket::SocketError)),
    //        this, SLOT(onError(QAbstractSocket::SocketError)));

    connect(this, SIGNAL(error(QAbstractSocket::SocketError)),
            this, SLOT(onError(QAbstractSocket::SocketError)));


    //有数据
    connect(this, SIGNAL(readyRead()), this, SLOT(onReadyRead()));

    connect(this, SIGNAL(bytesWritten(qint64)), this, SLOT(onBytesWritten(qint64)));

    connect(this, SIGNAL(aboutToClose()), this, SLOT(onAboutToClose()));

    connect(this, SIGNAL(readChannelFinished()), this, SLOT(onReadChannelFinished()));



    m_unPort = 0;
    m_nStep = 0;

    m_AutoConnect = false;



    //inFlag = false;
    m_bOutFlag = false;
    m_unInBlockSize = 0;
    m_ucInControlByte = 0;

    m_nMaxDataCacheSize = MAXDATACACHESIZE;
    //cachePos = 0;
    //cacheWriteFlag = true;

    //outTransfersCode = -1;


    //m_baPackageHeaderFlag.clear();

    m_dsOut.setVersion(QDataStream::Qt_5_9);
    m_dsIn.setVersion(QDataStream::Qt_5_9);
}

TcpSocket::~TcpSocket()
{
    clearAll();

    //if(state() == ConnectedState)
    //    onDisconnected();

    qDebug()<<"[Socket]TcpSocket析构:"<<this;
}


QDataStream &TcpSocket::sendData(quint8 outControlbyte)
{
    //如果 之前不存在发送数据,则初始化
    if(m_bOutFlag == false)
    {
        if(m_baPackageHeaderFlag.length() > 0)  //复制 包头标志
            m_dsOut.writeRawData(m_baPackageHeaderFlag,m_baPackageHeaderFlag.length());

        m_dsOut << quint8(outControlbyte);    //控制字符预留
        m_dsOut << quint32(0);  //数据长度预留
        m_bOutFlag = true;

        qDebug()<<"[Socket]sendData初始化(缓存长度):"<<m_baOutBlock.size();
    }
    return m_dsOut;
}

qint64 TcpSocket::send(bool bufferFlag)
{
    //if(m_baOutBlock.size() < 32768 / 2)
    //if(m_bOutFlag == false)  //有可能重发,所以不能判断!
    //    return -2;

    qint64 ret = -1;

    quint32 totalDataLength = m_baOutBlock.size()// - cachePos
            - m_baPackageHeaderFlag.length() - sizeof(quint8) - sizeof(quint32);
    qDebug()<<"[Socket]send:本次发送的数据长度(totalDataLength):"<<totalDataLength;

    /*
    if(totalDataLength > 1000)
        qDebug()<<"[Socket]send:本次发送的数据长度(totalDataLength):"<<totalDataLength;
    */


    //修复包长度
    //if(cachePos < m_baOutBlock.size())  //如果有新数据增加,则修复包长度
    if(m_bOutFlag == true)
    {
        m_dsOut.device()->seek(/*cachePos*/ + m_baPackageHeaderFlag.length() + sizeof(quint8));
        m_dsOut << (quint32)totalDataLength;
        m_dsOut.device()->seek(m_baOutBlock.size());
        //m_dsOut.device()->reset();
    }


    //如果没连接,但是缓存标志为true
    if(state() != QTcpSocket::ConnectedState && bufferFlag == true)
    {
        //cachePos = m_baOutBlock.size();        //缓存
        m_baOutBuffer.append(m_baOutBlock);
        clearOutData();
        //qDebug()<<"[Socket]发送数据被缓存(缓存大小):" << cachePos;
        ret = -2;
    }
    if(state() == QTcpSocket::UnconnectedState)
    {
        clearOutData();

        if(m_AutoConnect == true)
            connectServer();

        //qDebug() << "connecting1...";
        //ret = sendAndReset();
        ret = 0;
        //qDebug() << "connecting2...";
    }
    if(state() == QTcpSocket::ConnectedState)
    {
        //qDebug() << "connected1...";
        ret = sendAndReset();
        //qDebug() << "connected2...";
    }

    return ret;
}

void TcpSocket::clearOutData(bool bClearBuffer)
{
    m_baOutBlock.clear();
    m_dsOut.device()->seek(0);
    m_bOutFlag = false;
    if(bClearBuffer)
        m_baOutBuffer.clear();
    //cachePos = 0;
}

/*
bool TcpSocket::recievedDataValid()
{
    return inFlag;
}
*/




/*quint32 TcpSocket::recievedDataSize()
{
    return m_unInBlockSize;
}*/

QDataStream &TcpSocket::recievedData()
{
    /*
    if(inFlag == true)  //用一次后，就设置为false，继续下次的识别
    {
        qDebug()<<"[Socket][接受]开始读数据";
        m_unInBlockSize = 0;
        inFlag = false;
    }
    else
    {
        //qDebug()<<"[!Socket]无数据可读";
    }*/
    return m_dsIn;
}





void TcpSocket::onHostFound()
{
    emit s_hostFound(this);
    qDebug() << "[Socket]onHostFound";
}

void TcpSocket::onConnected()
{
    emit s_connected(this);
    qDebug() << "[Socket]onConnected";
}

void TcpSocket::onDisconnected()
{
    //if (nextBlockSize != 0xFFFF)        //服务端没有发送正常断开连接信息
    //    (tr("Error: Connection closed by server"));
    //disconnectFromHost();
    //waitForDisconnected();
    //close();

    emit s_disconnected(this);

    //deleteLater();
}


void TcpSocket::onReadyRead()
{
    //if(recievedDataValid() == false)
    //    return;

    qDebug()<<"[Socket]onReadyRead:未读数据字节:"<<bytesAvailable()
           <<"数据识别长度(m_unInBlockSize):"<<m_unInBlockSize;

    while(1)
    {
        //读取标志字符
        if(m_nStep == 0)
        {
            if(bytesAvailable() >= m_baPackageHeaderFlag.length())
            {
                //找到 头标志
                int index = this->peek(bytesAvailable()).indexOf(m_baPackageHeaderFlag,pos());
                if(index >= 0)
                {
                    //this->read(index);  //释放无用的
                    //this->seek(index);
                    m_dsIn.skipRawData(index - pos() + m_baPackageHeaderFlag.length());
                    m_nStep = 1;
                    qDebug()<<"[Socket]Recieved:标志串识别pos:"<<index;
                }
                else
                {
                    qDebug()<<"[Socket]Recieved:数据中找不到标志,继续等待接收!";

                    //!!!如果缓存数大于 m_nMaxDataCacheSize ,则释放掉无用的数据(最多留 m_baPackageHeaderFlag.length() - 1 个)
                    if(bytesAvailable() > m_nMaxDataCacheSize)
                    {
                        int n = bytesAvailable() - (m_baPackageHeaderFlag.length() - 1);
                        m_dsIn.skipRawData(n);
                        qDebug()<<"[Socket]Recieved:释放无用数据:"<<n<<"个字节";
                    }
                    break;
                }
            }
            else
                break;
        }

        //读取控制字符
        //if (m_unInBlockSize == 0 && bytesAvailable() >= sizeof(quint32))
        if(m_nStep == 1 && bytesAvailable() >= (qint32)sizeof(quint8))
        {
            m_dsIn >> m_ucInControlByte;
            m_nStep = 2;
            qDebug()<<"[Socket]Recieved:控制字符识别:"<<m_ucInControlByte;
        }

        //读长度部分,没有读取过头部(长度)
        //if (m_unInBlockSize == 0 && bytesAvailable() >= sizeof(quint32))
        if(m_nStep == 2)
        {
            if(bytesAvailable() >= (qint32)sizeof(quint32))
            {
                m_dsIn >> m_unInBlockSize;
                m_nStep = 3;
                qDebug()<<"[Socket]Recieved:数据长度识别:"<<m_unInBlockSize;

                if(m_unInBlockSize == 0)
                {
                    //m_nStep = 0;     //如果接受的数据长度为0,则返回第0步
                }
            }
            else
                break;
        }

        //读数据部分
        //是否有块的容量大小这么多字节可以读取;如果没有,就先在这里停止。当有更多数据可以读取的时候，readyRead()信号将会被再次发射，然后就可以再次尝试读取。
        //if (m_unInBlockSize != 0 && bytesAvailable() >= m_unInBlockSize)
        if (m_nStep == 3)
        {
            if(bytesAvailable() >= m_unInBlockSize)
            {
                qDebug() << "[Socket]Recieved:数据接收完整可以读取,数据长度/共可读:"
                       << m_unInBlockSize << "/" << bytesAvailable();

                //存一个完整数据到baData
                //QByteArray baData(m_unInBlockSize, Qt::Uninitialized);
                //m_dsIn.readRawData(baData.data(), m_unInBlockSize);

                /*检测包ID
                QByteArray b = this->peek(m_unInBlockSize + sizeof(int));
                QDataStream d(b);
                d.device()->seek(m_unInBlockSize);
                int pID;
                d >> pID;
                qDebug() << "[!!!包ID:]" << pID;
                */

                m_nStep = 0;
                m_unInBlockSize = 0;

                switch (m_ucInControlByte)
                {
                case (quint8)0x8b:   //请求n个Code
                    //((Server*)param)->createTransmitsCodeAndSend(pClientInfo);
                    break;
                case (quint8)0x8c:   //接受到n个Code
                    m_dsIn >> m_listOutTransfersCode;
                    emit s_readyRead(this);
                    break;
                //case (quint8)0x8d:
                //    break;
                default:
                    emit s_readyRead(this);
                    break;
                }
            }
            else
                break;

        }
        //释放掉已经用了的数据(TCP自动释放!)
        //pClientInfo->baIn.remove(0,pClientInfo->dsIn.device()->pos());
        //pClientInfo->dsIn.device()->reset();
    }
}


void TcpSocket::onStateChanged(QAbstractSocket::SocketState state)
{
    emit s_stateChanged(state,this);
    qDebug() << "[Socket]onStateChanged:"<<state<<"->"<<(qint16)state;
}

void TcpSocket::onError(QAbstractSocket::SocketError socketError)
{
    /*
    switch (socketError) {
    case QAbstractSocket::RemoteHostClosedError:
        break;
    case QAbstractSocket::HostNotFoundError:
        QMessageBox::information(nullptr, tr("深林孤鹰"),
                                 tr("The host was not found. Please check the "
                                    "host name and port settings."));
        break;
    case QAbstractSocket::ConnectionRefusedError:
        QMessageBox::information(nullptr, tr("深林孤鹰"),
                                 tr("The connection was refused by the peer. "
                                    "Make sure the fortune server is running, "
                                    "and check that the host name and port "
                                    "settings are correct."));
        break;
    case QAbstractSocket::NetworkError:
        QMessageBox::information(nullptr, tr("深林孤鹰"),
                                 tr("Network unreachable"));
        break;
    default:
        QMessageBox::information(nullptr, tr("深林孤鹰"),
                                 tr("Network Error:%1(%2)")
                                 .arg(pTcpSocket->errorString() ////为最后一次发生的错误返回一个用户可读的出错信息。
                                 .arg(socketError)));
    }
    */
    emit s_error(socketError, this);
}


void TcpSocket::onBytesWritten(qint64 bytes)
{
    emit s_bytesWritten(bytes,this);
    qDebug() << "[Socket]onBytesWritten";
}
void TcpSocket::onAboutToClose()
{
    emit s_aboutToClose(this);
    qDebug() << "[Socket]onAboutToClose";
}
void TcpSocket::onReadChannelFinished()
{
    emit s_readChannelFinished(this);
    qDebug() << "[Socket]onReadChannelFinished";
}
